package com.sprouting.personal.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.sprouting.personal.interfaces.common.Constant;
import com.sprouting.personal.model.entity.Config;
import com.sprouting.personal.model.entity.DatabaseBackup;
import com.sprouting.personal.service.ConfigService;
import com.sprouting.personal.service.DatabaseBackupService;
import com.sprouting.personal.utils.EntityTool;
import com.sprouting.personal.utils.IdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.File;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 数据库备份
 *
 * @author ：LX（长沙麓谷）
 * @date 创建时间： 2023/1/29 13:32
 */
@Component
@Slf4j
public class DatabaseBackupTask {

    @Autowired
    private DatabaseBackupService databaseBackupService;
    @Autowired
    private ConfigService configService;


    /**
     * 获取到数据库连接
     */
    @Value("${spring.datasource.url}")
    private String databaseUrl;

    /**
     * 开始备份
     * 3600000 = 1小时一次
     */
    @Scheduled(fixedRate = 7200000)
    public void start(){
        log.info("[数据库备份] 准备进行数据库备份");
        Integer exists = configService.getWhetherTableExists("ps_upload_file");
        if (exists < 1){
            log.info("[数据库备份] 当前表还未构建成功，初始化中，停止任务");
            return;
        }

        // 先检测是否开启了数据库备份
        Config config = configService.getConfigByCode(Constant.ConfigCode.DATABASE_BACKUP, null);
        if (!Boolean.valueOf(config.getValue())){
            log.info("[数据库备份] 未开启数据库备份，退出任务!");
            return;
        }

        // 检测是否已经备份过
        DatabaseBackup backLatest = databaseBackupService.getBackLatest();
        String now = DateUtil.today();
        if (backLatest != null){
            Date backTime = backLatest.getBackTime();
            String backTimeFormat = DateUtil.formatDate(backTime);
            if (now.equals(backTimeFormat)){
                log.info("[数据库备份] 今日已备份，不进行重复备份");
                return;
            }
        }
        if (!databaseUrl.contains("sqlite")){
            log.warn("[数据库备份] 当前使用数据库无法识别，暂时只支持sqlite数据库");
            return;
        }

        // 开始备份
        String path = databaseUrl.substring(databaseUrl.indexOf("sqlite:")).replace("sqlite:", "");
        // 备份在同一级目录下
        if (!FileUtil.exist(path)){
            log.error("[数据库备份] 数据库路径异常，未查询到数据库:{}", path);
            return;
        }

        String parent = FileUtil.getParent(path, 1);
        // 获取文件名带后缀
        String mainName = FileUtil.mainName(path);
        String newPath = parent + Constant.Base.DISK_SYMBOL + "bak" + Constant.Base.DISK_SYMBOL + mainName + "-" + now + "." + FileUtil.extName(path);

        TimeInterval startBack = DateUtil.timer();
        FileUtil.copy(path, newPath, false);
        // 耗时
        long interval = startBack.interval();

        // 记录备份信息
        DatabaseBackup databaseBackup = new DatabaseBackup();
        databaseBackup.setId(IdTool.getId());
        databaseBackup.setBackTime(new Date());
        databaseBackup.setBackPath(newPath);
        databaseBackup.setConsuming(interval);
        databaseBackup.setOriginalSize(new File(path).length());
        EntityTool.buildSaveBase(databaseBackup, "sys");
        databaseBackupService.save(databaseBackup);

        // 将旧的数据清理
        List<DatabaseBackup> list = databaseBackupService.list();
        // 排序
        List<DatabaseBackup> backupList = list.stream().sorted(Comparator.comparing(DatabaseBackup::getBackTime).reversed()).collect(Collectors.toList());
        // 只保存3天的数据，其他的要进行删除
        List<DatabaseBackup> subList = CollUtil.sub(backupList, 4, backupList.size());
        if (CollUtil.isEmpty(subList)){
            return;
        }
        for (DatabaseBackup backup : subList){
            // 要删除的
            FileUtil.del(backup.getBackPath());
            databaseBackupService.removeById(backup.getId());
            log.info("[数据库备份] 删除旧的备份数据:{}", backup.getBackPath());
        }

        log.info("[数据库备份] 数据库备份完成");
    }

}
